import { Vector2 } from "three";
import MathUtil from "./MathUtil";
import NodeLink from "./NodeLink";
import SegmentUtil from "./Segment";

export default class PolygonUtil {

    private constructor() { }


    /**
    * 两个矩形是否相交
    * @param rect1 
    * @param rect2 
    */
    static intersectRect(rect1: Array<Vector2>, rect2: Array<Vector2>): boolean {
        if (!rect1 || !rect2 || rect1.length != 4 || rect2.length != 4) {
            return false;
        }

        let lb = MathUtil.getExtremesBox(rect1);
        let rb = MathUtil.getExtremesBox(rect2);

        if (lb.min.x > rb.max.x || lb.min.y > rb.max.y || lb.max.x < rb.min.x || lb.max.y < rb.min.y) {
            return false;
        }

        return true;
    }

    /**
    * 矩形1是否被矩形2包含
    * @param rect1 
    * @param rect2 
    */
     static includeRect(rect1: Array<Vector2>, rect2: Array<Vector2>): boolean {
        if (!rect1 || !rect2 || rect1.length != 4 || rect2.length != 4) {
            return false;
        }

        let lb = MathUtil.getExtremesBox(rect1);
        let rb = MathUtil.getExtremesBox(rect2);

        if (lb.min.x >= rb.min.x && lb.min.y >= rb.min.y && lb.max.x <= rb.max.x && lb.max.y <= rb.max.y) {
            return true;
        }

        return false;
    }


    /**
     * 点是否在矩形内
     * @param v 
     * @param p 
     */
    static pointIsInPolygon(v: Vector2, p: Array<Vector2> | NodeLink): boolean {
        let box = p instanceof NodeLink ? MathUtil.getExtremesBox2(p) : MathUtil.getExtremesBox(p);
        if (v.x > box.min.x && v.y >= box.min.y && v.x <= box.max.x && v.y <= box.max.y) {
            return true;
        }

        return false;
    }


    /** 
     * 两个矩形组成的路径 只考虑矩形的情况
     * 
    */
    static rectUnionToPath(rect1: Array<Vector2>, rect2: Array<Vector2>): Array<any> {
        if (this.intersectRect(rect1, rect2)) {
            let lb = MathUtil.getExtremesBox(rect1);
            let rb = MathUtil.getExtremesBox(rect2);

            //全相交
            if (lb.min.x <= rb.min.x && lb.min.y <= rb.min.y && lb.max.x >= rb.max.x && lb.max.y >= rb.max.y) {
                return [rect1];
            }

            if (lb.min.x >= rb.min.x && lb.min.y >= rb.min.y && lb.max.x <= rb.max.x && lb.max.y <= rb.max.y) {
                return [rect2];
            }


            //有两条边共线的情况
            let lx = lb.max.x - lb.min.x;
            let rx = rb.max.x - rb.min.x;
            let ly = lb.max.y - lb.min.y;
            let ry = rb.max.y - rb.min.y;

            if( Math.abs(rx - lx) < 0.001 || Math.abs(ry - ly) < 0.001 ){
                lb.union(rb);
                return [
                    new Vector2(lb.min.x, lb.min.y),
                    new Vector2(lb.max.x, lb.min.y),
                    new Vector2(lb.max.x, lb.max.y),
                    new Vector2(lb.min.x, lb.max.y)

                ];
            }

            //错位

            MathUtil.toAntiClockWise(rect1);
            let alink = new NodeLink().setFromArray(rect1);

            MathUtil.toAntiClockWise(rect2)
            let blink = new NodeLink().setFromArray(rect2);

            //当前的游标
            let curr = alink;
            //检测的矩形
            // let tLink = blink;
            let checkIndex = 1;

            let result = [];

            let count = 0;

            do {

                count++;
                if(count >= 10000){
                    return [];
                }
                let count2 = 0;

                result.push(curr.node);
                let end = curr.next;

                let intersect = [];

                //需要检测交点的矩形
                let check = checkIndex == 1 ? blink : alink;
                //当前的矩形
                let main = checkIndex == 0 ? blink : alink;

                let iterator = check;

                do {

                    count2++;
                    if(count2 >= 10000){
                        return [];
                    }
                    
                    let tn = iterator.next;

                    //找到交点
                    let p = SegmentUtil.segmentIntersect([curr.node, end.node], [iterator.node, tn.node]);
                    p && intersect.push({ intersect: p, start: iterator, end: tn });

                    //下一条线段
                    iterator = tn;
                } while (iterator != check);



                //如果有交点
                if (intersect.length > 0) {
                    let p = this.sortByDis(curr.node, intersect);

                    //记录当前交点的信息
                    let ip = p.intersect;
                    let start = p.start;
                    let end = p.end;

                    result.push(ip);



                    //记录当前点，连接下一个点
                    // let node = new NodeLink();
                    // node.node = ip;
                    // node.next = ;

                    
                    curr = this.pointIsInPolygon(start.node, main) ? end : start;


                    checkIndex = (checkIndex + 1) % 2;
                }
                else {

                    curr = curr.next;
                }
            } while (curr != alink);


            return [result];

        }

        return [rect1, rect2];
    }


    /**
     * 排序
     */
    static sortByDis(p: Vector2, ps: Array<Record<"intersect" | "start" | "end", any>>): Record<"intersect" | "start" | "end", any> {
        let dis = Infinity, r = null;
        for (let i of ps) {
            let iv = i.intersect;
            let cd = p.distanceTo(iv);
            if (cd < dis) {
                r = i;
            }
        }

        return r;
    }
}